/**
 * @author		Ben Layet
 * @version 	1.0
 * @date		25 Sep 2008
 */
package org.ignoramus.application.store;

import java.io.IOException;
import java.io.InputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.ignoramus.application.model.CardTemplate;
import org.ignoramus.application.model.CardTemplateElement;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * The XML Template data parser.
 */
public class TemplateParser
{
	/** title tag. */
	private static final String	title_tag	= "title";
	/** element tag. */
	private static final String	element_tag		= "element";
	/** question_mode attribute. */
	private static final String	question_mode_attribute	= "question_mode";
	/** src attribute. */
	private static final String	src_attribute	= "src";
	/** name attribute. */
	private static final String	name_attribute	= "name";
	/** checker attribute. */
	private static final String	checker_attribute	= "checker";

	/** The input stream data. */
	private final InputStream	data;

	/** The Card template. */
	private CardTemplate				template			= null;

	/**
	 * Constructs with the input stream data.
	 * 
	 * @param data
	 *            the input stream data.
	 */
	public TemplateParser(InputStream data)
	{
		this.data = data;
	}

	/**
	 * parses the file.
	 * 
	 * @throws StoreException
	 *             if the file cannot be parsed.
	 */
	private void parse() throws StoreException
	{
		// check if it has already been parsed
		if (template == null)
		{
			// document builder factory
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			try
			{
				// document builder
				DocumentBuilder db = dbf.newDocumentBuilder();
				// parse the document
				Document doc = db.parse(data);
				// normalise the document
				doc.getDocumentElement().normalize();

				// get the title element
				Element element = (Element) doc.getElementsByTagName(title_tag).item(0);
				// set the title
				String title = element.getAttribute(src_attribute);
				
				//Create the template
				template = new CardTemplate(title);
				
				// get the elements
				NodeList tplElemNodes = doc.getElementsByTagName(element_tag);
				
				//loop through the card nodes
				for (int i = 0; i < tplElemNodes.getLength(); i++)
				{
					//get the next template element
					Element tplElement = (Element) tplElemNodes.item(i);
					//get the question_mode
					String questionMode = tplElement.getAttribute(question_mode_attribute);
					//get the src
					String src = tplElement.getAttribute(src_attribute);
					//get the name
					String name = tplElement.getAttribute(name_attribute);
					//get the checker name
					String checkerName = tplElement.getAttribute(checker_attribute);
					
					//create the template element
					template.put(src, new CardTemplateElement(checkerName, name, questionMode, src));
				}
				
				// close the input stream
				data.close();

			}
			catch (ParserConfigurationException e)
			{
				throw new StoreException("Cannot parse the lesson file.", e);
			}
			catch (SAXException e)
			{
				throw new StoreException("Cannot parse the lesson file.", e);
			}
			catch (IOException e)
			{
				throw new StoreException("Cannot parse the lesson file.", e);
			}
		}
	}

	/**
	 * @returns the template.
	 * @throws StoreException
	 *             if the file cannot be parsed.
	 */
	public CardTemplate getTemplate() throws StoreException
	{
		parse();
		return template;
	}

}
